#!/usr/bin/env python3
"""
Matter温控器数据解析器
解析chip-tool输出的温控器属性数据
"""

import re
from dataclasses import dataclass
from typing import Dict, Optional, List, Tuple
import time


@dataclass
class ThermostatData:
    """温控器数据结构"""
    # 温度相关
    local_temperature: Optional[float] = None
    
    # 加热限制
    abs_min_heat_setpoint_limit: Optional[float] = None
    abs_max_heat_setpoint_limit: Optional[float] = None
    min_heat_setpoint_limit: Optional[float] = None
    max_heat_setpoint_limit: Optional[float] = None
    occupied_heating_setpoint: Optional[float] = None
    
    # 制冷限制
    abs_min_cool_setpoint_limit: Optional[float] = None
    abs_max_cool_setpoint_limit: Optional[float] = None
    min_cool_setpoint_limit: Optional[float] = None
    max_cool_setpoint_limit: Optional[float] = None
    occupied_cooling_setpoint: Optional[float] = None
    
    # 系统设置
    min_setpoint_dead_band: Optional[float] = None
    control_sequence_of_operation: Optional[int] = None
    system_mode: Optional[int] = None
    thermostat_running_state: Optional[int] = None


class ThermostatParser:
    """温控器数据解析器"""
    
    def __init__(self):
        # 定义属性映射关系
        # 格式: (正则表达式模式, 数据类字段名, 转换函数)
        self.attribute_patterns = [
            (r'LocalTemperature:\s*(-?\d+)', 'local_temperature', lambda x: float(x) / 100),
            (r'AbsMinHeatSetpointLimit:\s*(-?\d+)', 'abs_min_heat_setpoint_limit', lambda x: float(x) / 100),
            (r'AbsMaxHeatSetpointLimit:\s*(-?\d+)', 'abs_max_heat_setpoint_limit', lambda x: float(x) / 100),
            (r'AbsMinCoolSetpointLimit:\s*(-?\d+)', 'abs_min_cool_setpoint_limit', lambda x: float(x) / 100),
            (r'AbsMaxCoolSetpointLimit:\s*(-?\d+)', 'abs_max_cool_setpoint_limit', lambda x: float(x) / 100),
            (r'OccupiedCoolingSetpoint:\s*(-?\d+)', 'occupied_cooling_setpoint', lambda x: float(x) / 100),
            (r'OccupiedHeatingSetpoint:\s*(-?\d+)', 'occupied_heating_setpoint', lambda x: float(x) / 100),
            (r'MinHeatSetpointLimit:\s*(-?\d+)', 'min_heat_setpoint_limit', lambda x: float(x) / 100),
            (r'MaxHeatSetpointLimit:\s*(-?\d+)', 'max_heat_setpoint_limit', lambda x: float(x) / 100),
            (r'MinCoolSetpointLimit:\s*(-?\d+)', 'min_cool_setpoint_limit', lambda x: float(x) / 100),
            (r'MaxCoolSetpointLimit:\s*(-?\d+)', 'max_cool_setpoint_limit', lambda x: float(x) / 100),
            (r'MinSetpointDeadBand:\s*(-?\d+)', 'min_setpoint_dead_band', lambda x: float(x) / 100),
            (r'ControlSequenceOfOperation:\s*(\d+)', 'control_sequence_of_operation', int),
            (r'SystemMode:\s*(\d+)', 'system_mode', int),
            (r'ThermostatRunningState:\s*(\d+)', 'thermostat_running_state', int),
        ]
        
        # 也支持从原始数据中直接提取数值（当没有格式化输出时）
        self.raw_data_patterns = [
            (r'Attribute\s+0x0000_0000.*Data\s*=\s*(-?\d+)', 'local_temperature', lambda x: float(x) / 100),
        ]
    
    def parse_output(self, output: str) -> ThermostatData:
        """
        解析chip-tool输出
        
        Args:
            output: chip-tool的完整输出文本
            
        Returns:
            解析后的温控器数据
        """
        data = ThermostatData()
        
        # 首先尝试解析格式化的输出
        for pattern, field_name, converter in self.attribute_patterns:
            match = re.search(pattern, output, re.IGNORECASE | re.MULTILINE)
            if match:
                # 输出匹配到的原始内容
                print(f"匹配到 {field_name}: {match.group(0)}")
                try:
                    value = converter(match.group(1))
                    setattr(data, field_name, value)
                except (ValueError, IndexError) as e:
                    print(f"警告: 解析字段 {field_name} 时出错: {e}")
        
        # 如果没有找到格式化输出，尝试解析原始数据
        if data.local_temperature is None:
            for pattern, field_name, converter in self.raw_data_patterns:
                match = re.search(pattern, output, re.IGNORECASE | re.MULTILINE)
                if match:
                    # 输出匹配到的原始内容
                    print(f"匹配到原始数据 {field_name}: {match.group(0)}")
                    try:
                        value = converter(match.group(1))
                        setattr(data, field_name, value)
                    except (ValueError, IndexError) as e:
                        print(f"警告: 解析原始数据字段 {field_name} 时出错: {e}")
        
        return data
    
    def parse_to_dict(self, output: str) -> Dict:
        """
        解析输出并返回字典格式
        
        Args:
            output: chip-tool输出文本
            
        Returns:
            包含解析数据的字典
        """
        data = self.parse_output(output)
        
        return {
            'local_temperature_celsius': data.local_temperature,
            'heating_limits': {
                'absolute_min': data.abs_min_heat_setpoint_limit,
                'absolute_max': data.abs_max_heat_setpoint_limit,
                'min': data.min_heat_setpoint_limit,
                'max': data.max_heat_setpoint_limit,
                'occupied_setpoint': data.occupied_heating_setpoint
            },
            'cooling_limits': {
                'absolute_min': data.abs_min_cool_setpoint_limit,
                'absolute_max': data.abs_max_cool_setpoint_limit,
                'min': data.min_cool_setpoint_limit,
                'max': data.max_cool_setpoint_limit,
                'occupied_setpoint': data.occupied_cooling_setpoint
            },
            'system_settings': {
                'min_setpoint_dead_band': data.min_setpoint_dead_band,
                'control_sequence_of_operation': data.control_sequence_of_operation,
                'system_mode': data.system_mode,
                'thermostat_running_state': data.thermostat_running_state
            }
        }
    
    def get_control_sequence_description(self, sequence: Optional[int]) -> str:
        """获取控制操作序列的描述"""
        if sequence is None:
            return "未知"
        
        sequences = {
            0: "仅制冷",
            1: "制冷带再加热",
            2: "仅制热", 
            3: "制热带再制冷",
            4: "制热和制冷",
            5: "制冷和制热带在加热"

        }
        return sequences.get(sequence, f"未知 ({sequence})")
    
    def get_system_mode_description(self, mode: Optional[int]) -> str:
        """获取系统模式的描述"""
        if mode is None:
            return "未知"
        
        modes = {
            0: "关闭",
            1: "自动",
            2: "无该模式",
            3: "制冷",
            4: "制热",
            5: "紧急制热",
            6: "预制冷",
            7: "仅风扇",
            8: "干燥",
            9: "睡眠",
        }
        return modes.get(mode, f"未知 ({mode})")
    
    def get_running_state_description(self, state: Optional[int]) -> str:
        """获取运行状态的描述 - 基于RelayStateBitmap位图解析"""
        if state is None:
            return "未知"
        
        if state == 0:
            return "所有设备关闭"
        
        # 解析RelayStateBitmap位图
        states = []
        
        # 检查每个位的状态
        if state & 0x01:  # Bit 0: Heat
            states.append("加热开启")
        
        if state & 0x02:  # Bit 1: Cool
            states.append("制冷开启")
        
        if state & 0x04:  # Bit 2: Fan
            states.append("风扇开启")
        
        if state & 0x08:  # Bit 3: HeatStage2
            states.append("加热2段开启")
        
        if state & 0x10:  # Bit 4: CoolStage2
            states.append("制冷2段开启")
        
        if state & 0x20:  # Bit 5: FanStage2
            states.append("风扇2段开启")
        
        if state & 0x40:  # Bit 6: FanStage3
            states.append("风扇3段开启")
        
        if states:
            return ", ".join(states)
        else:
            return f"未知状态 (0x{state:02X})"


def format_thermostat_data(data: ThermostatData) -> str:
    """
    格式化温控器数据为易读的字符串
    
    Args:
        data: 温控器数据对象
        
    Returns:
        格式化的字符串
    """
    parser = ThermostatParser()
    output = []
    output.append("🌡️  温控器数据报告")
    output.append("=" * 40)
    
    # 温度信息
    if data.local_temperature is not None:
        output.append(f"📡 当前温度: {data.local_temperature:.2f}°C")
    else:
        output.append("📡 当前温度: 未知")
    
    output.append("")
    
    # 加热限制
    output.append("🔥 加热限制:")
    if data.abs_min_heat_setpoint_limit is not None and data.abs_max_heat_setpoint_limit is not None:
        output.append(f"   绝对范围: {data.abs_min_heat_setpoint_limit:.2f}°C - {data.abs_max_heat_setpoint_limit:.2f}°C")
    
    if data.min_heat_setpoint_limit is not None and data.max_heat_setpoint_limit is not None:
        output.append(f"   设定范围: {data.min_heat_setpoint_limit:.2f}°C - {data.max_heat_setpoint_limit:.2f}°C")
    
    if data.occupied_heating_setpoint is not None:
        output.append(f"   当前加热设定: {data.occupied_heating_setpoint:.2f}°C")
    
    output.append("")
    
    # 制冷限制
    output.append("❄️  制冷限制:")
    if data.abs_min_cool_setpoint_limit is not None and data.abs_max_cool_setpoint_limit is not None:
        output.append(f"   绝对范围: {data.abs_min_cool_setpoint_limit:.2f}°C - {data.abs_max_cool_setpoint_limit:.2f}°C")
    
    if data.min_cool_setpoint_limit is not None and data.max_cool_setpoint_limit is not None:
        output.append(f"   设定范围: {data.min_cool_setpoint_limit:.2f}°C - {data.max_cool_setpoint_limit:.2f}°C")
    
    if data.occupied_cooling_setpoint is not None:
        output.append(f"   当前制冷设定: {data.occupied_cooling_setpoint:.2f}°C")
    
    output.append("")
    
    # 系统设置
    output.append("⚙️  系统设置:")
    if data.min_setpoint_dead_band is not None:
        output.append(f"   最小设定点死区: {data.min_setpoint_dead_band:.2f}°C")
    
    if data.control_sequence_of_operation is not None:
        output.append(f"   控制操作序列: {parser.get_control_sequence_description(data.control_sequence_of_operation)}")
    
    if data.system_mode is not None:
        output.append(f"   系统模式: {parser.get_system_mode_description(data.system_mode)}")
    
    if data.thermostat_running_state is not None:
        output.append(f"   运行状态: {parser.get_running_state_description(data.thermostat_running_state)}")
    
    output.append("")
    output.append(f"📅 数据采集时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    
    return "\n".join(output)


def main():
    """测试函数"""
    # 测试数据
    sample_output = """
[TOO] Endpoint: 1 Cluster: 0x0000_0201 Attribute 0x0000_0000 DataVersion: 1527150028
[TOO]   LocalTemperature: 2100
"""
    
    parser = ThermostatParser()
    data = parser.parse_output(sample_output)
    
    print("解析结果:")
    print(format_thermostat_data(data))


if __name__ == "__main__":
    main()
